<?php

namespace app\common\business\http;

/**
 * http数据来源抽象类
 */
class AbstractModel {

    /**
     * 访问的host
     *
     * @var string
     */
    protected $_host = '';

    /**
     * 设置cookie
     *
     * @var array
     */
    protected $_cookies = array();

    /**
     * 构造函数，实现初始化host
     */
    public function __construct() {
        $this->_host = config("api_url");
    }

    /**
     * 发起HTTP请求
     *
     * @param string $url
     * @param string $method
     * @param array $params
     * @param int $timeout
     * @param array $extParams 扩展的参数信息，可以是cookie之类
     * @return boolean
     */
    protected function _request($url, $method = "GET", $params = array(), $timeout = 30, $extParams = array()) {
        $url = $this->_host . $url;
        $paramString = http_build_query($params, '', '&');
        if (strtoupper($method) == "GET" && $params) {
            $url .= "?" . $paramString;
        }
        $ch = curl_init($url);

        if (strtoupper($method) == "POST") {
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $paramString);
        }
        $time = time();
        $sign = $this->createVerifyData($params, $time);
        $headers = array(
            'sign:' . $sign,
            'keytime:' . $time
        );
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_HEADER, false);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
      //  curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
        if (!empty($extParams["cookies"])) {
            curl_setopt($ch, CURLOPT_COOKIE, $this->analyzeCookie($extParams["cookies"]));
        }
        
        //检测是否是https访问
        if (strpos($url, 'https') === 0) {
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        }  
        $result = curl_exec($ch); 
        //请求失败的处理方法
        if (curl_errno($ch)) {
            return false;
        }
        curl_close($ch);
        return $result;
    }

    /**
     * 解析cookie数组，转换成字符串形式
     *
     * @param array $cookies
     * @return string
     */
    public function analyzeCookie($cookies) {
        $cookie = '';
        foreach ($cookies as $key => $value) {
            $cookie = $key . '=' . $value . '; ';
        }

        return substr($cookie, 0, strlen($cookie) - 2);
    }

    /**
     * 获取主机地址
     *
     * @return string
     */
    public function getHost() {
        return $this->_host;
    }

    public function getCookies() {
        return $this->_cookies;
    }

    public function setCookies($cookie) {
        $this->_cookies = $cookie;
    }

    /**
     * 设置主机地址
     *
     * @return string
     */
    public function setHost($host) {
        $this->_host = $host;
    }

    public function getLastRequestUrl() {
        return $this->_lastRequestUrl;
    }

    public function setLastRequestUrl($lastRequestUrl) {
        $this->_lastRequestUrl = $lastRequestUrl;
    }

    /**
     * 除去数组中的空值和签名参数
     * 
     * @param type $para 签名参数组
     * @return type 去掉空值与签名参数后的新签名参数组
     */
    public function paraFilter($para) {
        $para_filter = array();
        while (list ($key, $val) = each($para)) {
            if ($key == "sign" || $key == "v" || $val == "" || $key == "sso") {
                continue;
            } else {
                $para_filter[$key] = $para[$key];
            }
        }
        return $para_filter;
    }

    /**
     * 对数组排序
     * 
     * @param type $para 排序前的数组
     * @return type 排序后的数组
     */
    public function argSort($para) {
        ksort($para);
        reset($para);
        return $para;
    }

    /**
     * 把数组所有元素，按照“参数值”的模式用“&”字符拼接成字符串,参数值不带引号
     * 
     * @param type $para 需要拼接的数组
     * @return type 拼接完成以后的字符串
     */
    public function createLinkstring($para) {
        $arg = "";
        while (list ($key, $val) = each($para)) {
            //$arg.=$key . "=" . $val . "&";
            $arg.=$val . "&";
        }
        //去掉最后一个&字符
        $arg = substr($arg, 0, count($arg) - 2);

        //如果存在转义字符，那么去掉转义
        if (get_magic_quotes_gpc()) {
            $arg = stripslashes($arg);
        }

        return $arg;
    }

    /**
     * 创建校验数据
     * 
     * @param type $post
     * @return type
     */
    public function createVerifyData($post, $time) {
        if (empty($post)) {
            $para_sort = array();
        } else {
            //除去待签名参数数组中的空值和签名参数
            $para_filter = $this->paraFilter($post);
            //对待签名参数数组排序
            $para_sort = $this->argSort($para_filter);
        }
        $para_sort['key_time'] = $time;
        $para_sort['key'] = config('api_sign_key');
        //把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
        $prestr = $this->createLinkstring($para_sort);
        return hash('sha256', $prestr);
    }

    /**
     * 禁止克隆
     */
    public function __clone() {
        trigger_error('Clone is not allow!', E_USER_ERROR);
    }

}
